﻿using System;
using System.IO.Packaging;
using OPCDiffCore;
using OPCDiffCore.Text;
using OPCDiffCore.Zip;
using OPCDiffCore.Relationship;
using OPCDiffCmd.Cartridge;

namespace OPCDiffCmd.Cartridge
{
    internal sealed class ConsoleCartridge : IOutputCartridge
    {
        public void BuildOutput(PackageDiff packageDiff)
        {
            if (packageDiff.CountPartDiff == 0)
                Console.WriteLine("Identical files !");
            else
            {
                Console.WriteLine("NOT identical files :\n");
                foreach (PartDiff partDiff in packageDiff.PartDiffs)
                {
                    switch (partDiff.DiffType)
                    {
                        case DiffType.Modified:
                            if (PackUriHelper.IsRelationshipPartUri(partDiff.PartUri))
                                Console.WriteLine(String.Format("Relationship part {0} MODIFIED:", partDiff.PartUri.ToString()));
                            else
                                Console.WriteLine(String.Format("Part {0} MODIFIED:",
                                    partDiff.PartUri));

                            // Display modified element
                            foreach (DiffElement diffElement in partDiff)
                            {
                                Console.WriteLine("   " + diffElement.ToString());

                                // Display specific change detail
                                switch (diffElement.Type)
                                {
                                    case DiffElementType.TextContent:
                                        LineChange lineChange = (LineChange)diffElement.Extra;
                                        foreach (InternalLineChange intLineChange in lineChange.Changes)
                                            Console.WriteLine(
                                                String.Format("      Line {0} from {1} to {2}: {3} -> {4}",
                                                intLineChange.DiffType,
                                                intLineChange.Start,
                                                intLineChange.End,
                                                intLineChange.ContentOriginal,
                                                intLineChange.ContentDiff));
                                        break;

                                    case DiffElementType.Relationship:
                                        RelationshipChange relChange = (RelationshipChange)diffElement.Extra;
                                        foreach (InternalRelationshipChange intRelChange in relChange.ChangeList)
                                        {
                                            string output = null;
                                            switch (relChange.DiffType)
                                            {
                                                case DiffType.Modified:
                                                    output = String.Format("      Property '{0}' modified: '{1}' -> '{2}'",
                                                        intRelChange.ChangedElement,
                                                        intRelChange.OldValue,
                                                        intRelChange.NewValue);
                                                    break;

                                                case DiffType.Added:
                                                    output = String.Format("      Property '{0}' added: '{1}'",
                                                                intRelChange.ChangedElement,
                                                                intRelChange.NewValue);
                                                    break;

                                                case DiffType.Removed:
                                                    output = String.Format("      Property '{0}' removed: '{1}'",
                                                        intRelChange.ChangedElement,
                                                        intRelChange.OldValue);
                                                    break;

                                            }
                                            Console.WriteLine(output);
                                        }
                                        break;

                                    case DiffElementType.BinaryContent:
                                        // TODO
                                        break;

                                    case DiffElementType.XmlContent:
                                        // TODO
                                        break;

                                    default:
                                        // TODO
                                        break;
                                }
                            }
                            break;

                        case DiffType.Removed:
                            if (PackUriHelper.IsRelationshipPartUri(partDiff.PartUri))
                                Console.WriteLine(String.Format("Relationship part {0} REMOVED.", partDiff.PartUri.ToString()));
                            else
                                Console.WriteLine(String.Format("Part {0} REMOVED.", partDiff.PartUri.ToString()));
                            break;

                        case DiffType.Added:
                            if (PackUriHelper.IsRelationshipPartUri(partDiff.PartUri))
                                Console.WriteLine(String.Format("Relationship part {0} ADDED.", partDiff.PartUri.ToString()));
                            else
                                Console.WriteLine(String.Format("Part {0} ADDED.", partDiff.PartUri.ToString()));
                            break;

                        default:
                            throw new InvalidProgramException("Must not have 'Unchanged' change !");
                    }
                }
            }

            Console.ReadLine();
        }
    }
}
